﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using CommandLists.Model;
using Eco.Handles;
using CommonClasses.Utility;
using System.IO;

namespace CommandLists.Controls
{
    /// <summary>
    /// Контрол, представляющий команду для списка команд.
    /// <see cref="CommandLists.Model.Command"/>
    /// </summary>
    public partial class CommandControl : UserControl
    {
        /// <summary>
        /// Цвет, используемый для рисования рамки при подсветке
        /// </summary>
        private Color highLightColor = Color.Empty;
        /// <summary>
        /// Флаг, показывающий, можно ли открывать меню параметров данной команды
        /// </summary>
        private bool canShowMenu = true;

        /// <summary>
        /// Команда, представленная данным контролом.
        /// </summary>
        public Command Command { get; private set; }

        /// <summary>
        /// Конструктор по умолчанию.
        /// </summary>
        public CommandControl()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Создать экземпляр класса CommandControl для указанной команды.
        /// </summary>
        /// <param name="source">Команда, содержимое которой будет представлено</param>
        public CommandControl(Command source)
            : this()
        {
            SetCommand(source);
        }

        #region Public methods

        /// <summary>
        /// Установить команду, которую будет представлять данный контрол
        /// </summary>
        /// <param name="source">Команда</param>
        public void SetCommand(Command source)
        {
            if (source == null)
                throw new NullReferenceException("Trying to create CommandControl instance with null source command!");

            Command = source;

            InitializeMenu();

            source.RefreshParameters();
            RefreshImage();
            Refresh();
        }

        /// <summary>
        /// Подсветить контрол (нарисовать рамку)
        /// </summary>
        /// <param name="color">Цвет, которым будет нарисована рамка</param>
        public void Highlight(Color color)
        {
            highLightColor = color;
            Refresh();
        }

        /// <summary>
        /// Снять подсветку с контрола.
        /// </summary>
        public void HighLightOff()
        {
            highLightColor = Color.Empty;
            Refresh();
        }

        /// <summary>
        /// Разрешить или запретить показывать меню параметров
        /// </summary>
        /// <param name="canShow">true - если можно показывать</param>
        public void SetCanShowMenu(bool canShow)
        {
            canShowMenu = canShow;
        }

        #endregion

        /// <summary>
        /// Сконфигурировать выпадающее меню для данного контрола
        /// </summary>
        private void InitializeMenu()
        {
            PopupMenu.Items.Clear();

            //если нет параметров - выходим
            if (Command.Parameters.Count == 0) return;

            //добавляем параметры
            foreach (var param in Command.Parameters)
            {
                if (param.Visible)
                {
                    //название параметра
                    var titleitem = new ToolStripMenuItem(param.Name);
                    //titleitem.Click += new EventHandler(titleitem_Click);
                    //titleitem.ForeColor = Color.Black;
                    PopupMenu.Items.Add(titleitem);

                    //поле радактирования параметра
                    var edititem = new ToolStripTextBox();
                    edititem.Tag = param;
                    edititem.Text = param.DefaultValue.ToString();
                    edititem.LostFocus += new EventHandler(edititem_LostFocus);
                    edititem.KeyUp += new KeyEventHandler(edititem_KeyPress);
                    PopupMenu.Items.Add(edititem);

                    //разделитель
                    var separator = new ToolStripSeparator();
                    PopupMenu.Items.Add(separator);
                }
                //название параметра
                var titlei = new ToolStripMenuItem("OK");
                PopupMenu.Items.Add(titlei);
            }

            //если парметров несколько, то необходимо стереть последний разделитель
            if (PopupMenu.Items.Count > 0)
                if (PopupMenu.Items[PopupMenu.Items.Count - 1] is ToolStripSeparator)
                    PopupMenu.Items.RemoveAt(PopupMenu.Items.Count - 1);
        }

        /// <summary>
        /// Вызывается при необходимости установить значение параметра команды
        /// </summary>
        /// <param name="sender">ToolStripTextBox, который отвечает за редактирование данного параметра</param>
        private void SetParameterValue(object sender)
        {
            if (!(sender is ToolStripTextBox)) return;

            var strip = sender as ToolStripTextBox;

            try
            {
                (strip.Tag as CommandParameter).DefaultValue = int.Parse(strip.Text);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Некорректное значение параметра: " + strip.Text,
                    "Ошибка!", MessageBoxButtons.OK, MessageBoxIcon.Error);
                strip.Text = (strip.Tag as CommandParameter).DefaultValue.ToString();
                return;
            }

            Command.RefreshParameters();
            RefreshImage();
            Refresh();
            PopupMenu.Close();
        }

        public void RefreshImage()
        {
            try
            {
                PathUtility.RestoreCurrentDirectory(Locality.ExeFile);
                if (Command.ImagePath != string.Empty)
                {

                    Image img = new Bitmap(Command.ImagePath);                    
                    if (Command.Parameters.Count == 1)
                    {                        
                        string text = Command.Parameters[0].DefaultValue.ToString();
                        Graphics g = Graphics.FromImage(img);
                        g.DrawString(text, new Font("Arial", 12, FontStyle.Bold), new SolidBrush(Color.MidnightBlue), new PointF(0, 0));
                    }
                    Image.Image = img;                    
                }
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException("Command.ImagePath refers to wrong file!", ex);
            }
        }

        #region Event handlers

        private void edititem_LostFocus(object sender, EventArgs e)
        {
            SetParameterValue(sender);
        }

        private void edititem_KeyPress(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
                SetParameterValue(sender);
        }

        private void CommandControl_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
                Parent.Focus();
        }

        private void PopupMenu_Opening(object sender, CancelEventArgs e)
        {
            if (!canShowMenu)
            {
                e.Cancel = true;
                return;
            }
            var menu = sender as ContextMenuStrip;
            foreach (var item in menu.Items)
                if (item is ToolStripTextBox)
                {
                    var strip = item as ToolStripTextBox;
                    strip.Text = (strip.Tag as CommandParameter).DefaultValue.ToString();
                }
        }

        private void Image_Paint(object sender, PaintEventArgs e)
        {
            var width = 3;
            var highlightPen = new Pen(highLightColor, width);
            e.Graphics.DrawLines(highlightPen,
                new Point[] { 
                    new Point(0, 0),
                    new Point(Width - width, 0),
                    new Point(Width - width, Height - width),
                    new Point(0, Height - width),
                    new Point(0, 0)
                });
        }

        #endregion
    }
}
